package com.wodogs.utils;

import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;

import javax.imageio.ImageIO;

import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.openqa.selenium.By;
import org.openqa.selenium.Cookie;
import org.openqa.selenium.Dimension;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.Platform;
import org.openqa.selenium.Point;
import org.openqa.selenium.TakesScreenshot;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.phantomjs.PhantomJSDriver;
import org.openqa.selenium.phantomjs.PhantomJSDriverService;
import org.openqa.selenium.remote.Augmenter;
import org.openqa.selenium.remote.BrowserType;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.openqa.selenium.support.ui.ExpectedCondition;
import org.openqa.selenium.support.ui.WebDriverWait;

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.wd.core.spring.support.SpringUtils;
import com.wodogs.recharge.entity.UserAccount;
import com.wodogs.utils.bean.PhantomjsConfig;
import com.wodogs.utils.bean.WfProxy;
import com.wodogs.utils.service.ProxyService;
import com.wodogs.utils.tools.CaptchaStore;

public class BaseManage {
	
	private Log logger = LogFactory.getLog(this.getClass().getName());  
	
	public BaseManage() {
		super();
	}

	protected WebDriver driver;
	
	protected String commentInputXpath;
	protected String commentSendBtnXpath;
	
	protected String toLoginBtnXpath;
	protected String loginNameXpath;
	protected String loginPwdXpath;
	protected String loginBtnXpath;
	protected String loginFormXpath;
	
	protected String usernameXpath;
	
	private String cookieDomain;
	
	private Set<Cookie> cookies;
	
	private boolean isLoginSuccess = false;
	
	/**
	 * 初始化浏览器
	 * @param proxy:代理
	 */
	protected void initDriver(WfProxy proxy){
		// 如果你的 FireFox 没有安装在默认目录，那么必须在程序中设置  
//    	System.setProperty("webdriver.firefox.bin", "D:\\Program Files (x86)\\Mozilla Firefox\\firefox.exe");  
        // 创建一个 FireFox 的浏览器实例  
		
//        WebDriver driver = new FirefoxDriver(TestService.getDr());  
		if(proxy == null){
			driver = new FirefoxDriver();
//			new ChromeDriver();
		}else{
			driver = new FirefoxDriver(ProxyService.getCap(proxy));
		}
	}
	
	protected void initPhantomJSDriver(){
		PhantomjsConfig config = (PhantomjsConfig)SpringUtils.getBean("phantomjsConfig");
		if(config != null && StringUtils.isNotBlank(config.getPath())){
			System.setProperty("phantomjs.binary.path", config.getPath());
//			System.setProperty("phantomjs.binary.path", "D:\\QQDownload\\phantomjs-2.1.1-windows\\bin\\phantomjs.exe");
		}
		
    	DesiredCapabilities dCaps = new DesiredCapabilities(BrowserType.PHANTOMJS, "", Platform.WIN8_1);
        dCaps.setJavascriptEnabled(true);
        dCaps.setCapability("takesScreenshot", false);
        dCaps.setCapability(PhantomJSDriverService.PHANTOMJS_PAGE_SETTINGS_PREFIX+"userAgent", "Mozilla/5.0 (Windows NT 8.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.75 Safari/537.36");
        dCaps.setCapability(PhantomJSDriverService.PHANTOMJS_PAGE_CUSTOMHEADERS_PREFIX+"Host", "www.battlenet.com.cn");
        dCaps.setCapability(PhantomJSDriverService.PHANTOMJS_PAGE_CUSTOMHEADERS_PREFIX+"Referer", "http://www.battlenet.com.cn/zh/");
        dCaps.setCapability(PhantomJSDriverService.PHANTOMJS_PAGE_CUSTOMHEADERS_PREFIX+"User-Agent", "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.75 Safari/537.36");
        
    	driver = new PhantomJSDriver(dCaps);
	}
	
	/**
	 * 第一次加载页面
	 * @param url
	 * @throws InterruptedException
	 */
	protected void initPage(String url) throws InterruptedException{
		driver.manage().timeouts().pageLoadTimeout(60, TimeUnit.SECONDS);
        // 让浏览器访问 Baidu  
        driver.get(url);  
        // 用下面代码也可以实现  
        // driver.navigate().to("http://www.baidu.com");  
	}
	
	public void login(UserAccount account) throws InterruptedException{
		if(account == null || StringUtils.isBlank(account.getAccount()) || StringUtils.isBlank(account.getPassword())){
			return;
		}
		try{
			//初始化浏览器
			initDriver(null);
			//加载页面
			initPage(account.getLogin_url());
			// 获取 网页的 title  
			logger.info("1 Page title is: " + driver.getTitle());
	        
	        //点击登录按钮//*[@id='header']/div/div/div[5]/a[1]
			click2ShowLoginForm();
			
			//等待登陆界面
	        waitLoginFormShows();
	        //输入账号密码并登录
	        doLogin(account);
	        
	        // 显示搜索结果页面的 title  
	        logger.info("2 Page title is: " + driver.getTitle());
	           
	        return;
		}catch(Exception ex){
			ex.printStackTrace();
		}finally{
			Thread.sleep(3000);
			//driver.close();
		}
		return;
	}
	
	/**
	 * 点击按钮弹出登录框
	 */
	protected void click2ShowLoginForm(){
		 WebElement btnLogin = driver.findElement(By.xpath(toLoginBtnXpath));
	     btnLogin.click();
	}
	
	protected void doLogin(UserAccount account){
        //把账号密码放进去
        doLoginSetNamePwd(account.getAccount(), account.getPassword());
        //先输入验证码后点登录按钮
        inputTestBeforeClicke();
//        logger.info(driver.getCurrentUrl());
        //点击登录按钮
        logger.debug("点击登录按钮 " + driver.getTitle());
        driver.findElement(By.xpath(loginBtnXpath)).click();
        //先点登录按钮，后输入验证码
        inputTestAfterClicke(account);
        //检查是否登录成功
        logger.debug("检查是否登录成功 " + driver.getTitle());
        checkLoginSuccess();
        logger.debug("登录成功 " + driver.getTitle());
	}
	
	protected void checkLoginSuccess(){
		try{
			//等五秒,验证是否登录成功.如果用户信息这个span里面有内容就说明登录成功
			(new WebDriverWait(driver, 10)).until(new ExpectedCondition<Boolean>() {  
				public Boolean apply(WebDriver d) {  
					boolean a = false;
					try{
						a = loginSuccessCondition(d);
					}catch(Exception ex){
						return a;
					}
					return a;
				}
			});
		}catch(Exception ex){
			throw new AppException(2,"密码错误");
		}
        this.cookies = driver.manage().getCookies();
	}
	
	/**
	 * 检测是否登陆成功
	 * @param d
	 * @return
	 */
	protected boolean loginSuccessCondition(WebDriver d){
//		WebElement e = d.findElement(By.xpath("//div[@id='js_member_pic']/a/span[2]"));
		WebElement e = d.findElement(By.xpath(usernameXpath));
		return StringUtils.isNotBlank(e.getText());  
	}
	
	protected void waitLoginFormShows(){
		//等待登录框
        (new WebDriverWait(driver, 5)).until(new ExpectedCondition<Boolean>() {  
        	public Boolean apply(WebDriver d) {  
        		WebElement e = d.findElement(By.xpath(loginFormXpath));
        		return e!=null;  
        	}
        });
	}
	
	public void doSth(String... a){
		
	}
	
	/**
	 * 拖动验证码
	 * @param d
	 * @return
	 */
	protected void inputTestBeforeClicke(){
//		//等三分钟，检测是否拖动极验成功
//        (new WebDriverWait(driver, 180)).until(new ExpectedCondition<Boolean>() {  
//        	public Boolean apply(WebDriver d) {  
////		//div[@class='gt_slider']/div[@class='gt_ajax_tip success']
////		WebElement e = d.findElement(By.xpath("//div[@class='gt_slider']/div[@class='gt_ajax_tip success']"));
////		return e!=null; 
//        		 WebElement e = d.findElement(By.xpath("//div[@class='gt_slider']/div[@class='gt_ajax_tip success']"));
//        		 return e!=null;
//        	}
//        });
	}
	
	protected void inputTestAfterClicke(UserAccount account){
//		//等三分钟，检测是否拖动极验成功
//        (new WebDriverWait(driver, 180)).until(new ExpectedCondition<Boolean>() {  
//        	public Boolean apply(WebDriver d) {  
////		//div[@class='gt_slider']/div[@class='gt_ajax_tip success']
////		WebElement e = d.findElement(By.xpath("//div[@class='gt_slider']/div[@class='gt_ajax_tip success']"));
////		return e!=null; 
//        		 WebElement e = d.findElement(By.xpath("//div[@class='gt_slider']/div[@class='gt_ajax_tip success']"));
//        		 return e!=null;
//        	}
//        });
	}
	
	protected void doLoginSetNamePwd(String loginName,String password){
		// 通过 id 找到 input 的 DOM  
        WebElement uid = driver.findElement(By.xpath(loginNameXpath));  
        uid.sendKeys(loginName); // 输入关键字  
        
        // 通过 id 找到 input 的 DOM  
        WebElement passwd = driver.findElement(By.xpath(loginPwdXpath));  
        passwd.sendKeys(password);  // 输入关键字  
	}
	
	
//	public void comment(WfArticle article, final String comment,WfAccount account,WfProxy proxy) throws InterruptedException{
//		if(account == null || article==null){
//			return;
//		}
//			
//		try{
//			//初始化浏览器
//			initDriver(proxy);
//			//加载页面
//			initPage(article.getUrl());
//			//把cookies加到页面
//			addCookies(account.getCookies(),account.getCookiesFull());
//			//第二次加载页面，使cookies生效
//			driver.get(article.getUrl());  
//	        // 获取 网页的 title  
//	        System.out.println("1 Page title is: " + driver.getTitle());  
//	        //发评论
//	        doComment(comment);
//	        
//	        Thread.sleep(3000);
//	  
//	        // 显示搜索结果页面的 title  
//	        System.out.println("2 Page title is: " + driver.getTitle());
//	           
//		}catch(Exception ex){
//			ex.printStackTrace();
//			return;
//		}finally{
//			Thread.sleep(1000);
//			driver.close();
//		}
//		
//	}
	
	protected void doComment(String comment) throws InterruptedException{
		//把评论内容塞进去
    	Thread.sleep(2000);
    	WebElement textarea = driver.findElement(By.xpath(commentInputXpath));
    	textarea.sendKeys(comment);
    	
    	//点击发送按钮
    	driver.findElement(By.xpath(commentSendBtnXpath)).click();
	}
	
	/**
	 * 添加cookies
	 * @param str
	 */
	protected void addCookies(String str,String cookieFull){
		//如果全属性的cookies是空的就先用键值对的cookies
		if(StringUtils.isBlank(cookieFull)){
			List<Cookie> cookies = str2Cookies(str);
			for(Cookie cookie:cookies){
				driver.manage().addCookie(cookie);
			}
		}
		Gson gson = new Gson();
		try{
			Type type = new TypeToken<Set<Cookie>>(){}.getType();
			Set<Cookie> set = gson.fromJson(cookieFull, type);
			if(set==null)return;
			
			if(cookieDomain == null){
				driver.manage().deleteAllCookies();
				for(Cookie c:set){
					try{
						driver.manage().addCookie(c);
					}catch(Exception ex){
						ex.printStackTrace();
					}
				}
			}else{
				for(Cookie c:set){
					try{
						Cookie c1 = new Cookie(c.getName(), c.getValue(), cookieDomain, c.getPath(), c.getExpiry(), c.isSecure(), c.isHttpOnly());
						driver.manage().addCookie(c1);
					}catch(Exception ex){
						ex.printStackTrace();
					}
				}
			}
		}catch(Exception ex){
			ex.printStackTrace();
		}
	}
	
	protected void snapshot2(WebDriver drivername, String filename) {
		// this method will take screen shot ,require two parameters ,one is
		// driver name, another is file name

		// File scrFile = drivername.getScreenshotAs(OutputType.FILE);
		// Now you can do whatever you need to do with it, for example copy
		// somewhere
		try {
			WebDriver augmentedDriver = new Augmenter().augment(drivername);
			File screenshot = ((TakesScreenshot) augmentedDriver).getScreenshotAs(OutputType.FILE);
			File file = new File("E:\\" + filename);
			FileUtils.copyFile(screenshot, file);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			System.out.println("Can't save screenshot");
			e.printStackTrace();
		} finally {
			System.out.println("screen shot finished");
		}
	}
	
	protected void snapshotElement(WebDriver drivername, WebElement webElement,String platformName,String fileName) {
		try {
			BufferedImage inputbig = createElementImage(driver, webElement);
			CaptchaStore fileStore = new CaptchaStore(platformName, fileName);
			
			fileStore.storePic(inputbig);
			
		} catch (IOException e) {
			System.out.println("Can't save screenshot");
			e.printStackTrace();
		} finally {
			System.out.println("screen shot finished");
		}
	}
	
	

	protected byte[] takeScreenshot(WebDriver driver) throws IOException {
		WebDriver augmentedDriver = new Augmenter().augment(driver);
		return ((TakesScreenshot) augmentedDriver).getScreenshotAs(OutputType.BYTES);
		// TakesScreenshot takesScreenshot = (TakesScreenshot) driver;
		// return takesScreenshot.getScreenshotAs(OutputType.BYTES);
	}

	protected BufferedImage createElementImage(WebDriver driver, WebElement webElement) throws IOException {
		// 获得webElement的位置和大小。
		Point location = webElement.getLocation();
		Dimension size = webElement.getSize();
		// 创建全屏截图。
		BufferedImage originalImage = ImageIO.read(new ByteArrayInputStream(takeScreenshot(driver)));
		// 截取webElement所在位置的子图。
		BufferedImage croppedImage = originalImage.getSubimage(location.getX(), location.getY(), size.getWidth(),
				size.getHeight());
		return croppedImage;
	}
	
	protected List<Cookie> str2Cookies(String str){
		List<Cookie> cookies = new ArrayList<Cookie>();
		if(StringUtils.isBlank(str)){
			return cookies;
		}
		return cookies;
	}

	public WebDriver getDriver() {
		return driver;
	}

	public void setDriver(WebDriver driver) {
		this.driver = driver;
	}
	
	public String getCommentInputXpath() {
		return commentInputXpath;
	}

	public void setCommentInputXpath(String commentInputXpath) {
		this.commentInputXpath = commentInputXpath;
	}

	public String getCommentSendBtnXpath() {
		return commentSendBtnXpath;
	}

	public void setCommentSendBtnXpath(String commentSendBtnXpath) {
		this.commentSendBtnXpath = commentSendBtnXpath;
	}

	public String getLoginNameXpath() {
		return loginNameXpath;
	}

	public void setLoginNameXpath(String loginNameXpath) {
		this.loginNameXpath = loginNameXpath;
	}

	public String getLoginPwdXpath() {
		return loginPwdXpath;
	}

	public void setLoginPwdXpath(String loginPwdXpath) {
		this.loginPwdXpath = loginPwdXpath;
	}

	public String getToLoginBtnXpath() {
		return toLoginBtnXpath;
	}

	public void setToLoginBtnXpath(String toLoginBtnXpath) {
		this.toLoginBtnXpath = toLoginBtnXpath;
	}

	public String getLoginBtnXpath() {
		return loginBtnXpath;
	}

	public void setLoginBtnXpath(String loginBtnXpath) {
		this.loginBtnXpath = loginBtnXpath;
	}

	public String getLoginFormXpath() {
		return loginFormXpath;
	}

	public void setLoginFormXpath(String loginFormXpath) {
		this.loginFormXpath = loginFormXpath;
	}

	public String getUsernameXpath() {
		return usernameXpath;
	}

	public void setUsernameXpath(String usernameXpath) {
		this.usernameXpath = usernameXpath;
	}

	public String getCookieDomain() {
		return cookieDomain;
	}

	public void setCookieDomain(String cookieDomain) {
		this.cookieDomain = cookieDomain;
	}

	public Set<Cookie> getCookies() {
		return cookies;
	}

	public void setCookies(Set<Cookie> cookies) {
		this.cookies = cookies;
	}

	public boolean isLoginSuccess() {
		return isLoginSuccess;
	}

	public void setLoginSuccess(boolean isLoginSuccess) {
		this.isLoginSuccess = isLoginSuccess;
	}

}
